package com.qing.common.executor

import android.annotation.SuppressLint
import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.MoreExecutors
import com.qing.common.base.BaseExecutor
import com.qing.common.util.LogUtil
import java.util.concurrent.Callable
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.ThreadFactory
import java.util.concurrent.TimeUnit

private const val TAG = "DefaultMainExecutor"

class DefaultBackgroundExecutor : BaseExecutor {

    private val mExecutorService by lazy {
        MoreExecutors.listeningDecorator(
            ScheduledThreadPoolExecutor(
                Runtime.getRuntime().availableProcessors(), DefaultBackgroundThreadFactory()
            )
        )
    }

    @SuppressLint("CheckResult")
    override fun executeDelayed(command: Runnable, delay: Long) {
        mExecutorService.schedule(command, delay, TimeUnit.MILLISECONDS)
    }

    override fun <T> listenerExecute(command: Callable<T>): ListenableFuture<T> {
        return mExecutorService.schedule(command, 0, TimeUnit.MILLISECONDS)
    }

    override fun post(command: Runnable) {
        execute(command)
    }

    override fun postDelayed(command: Runnable, delay: Long) {
        executeDelayed(command, delay)
    }

    override fun execute(command: Runnable) {
        mExecutorService.execute(command)
    }

    override fun close() {
        mExecutorService.shutdown()
    }

    private class DefaultBackgroundThreadFactory : ThreadFactory {
        private var mCount = 0
        override fun newThread(r: Runnable?): Thread {
            val thread = Thread(r, "Thread-${mCount++}")
            thread.uncaughtExceptionHandler = Thread.UncaughtExceptionHandler { t, e ->
                LogUtil.e(TAG, "catch thread uncaught exception: ", e)
            }
            return thread
        }
    }
}